package com.millstein.tsinglog.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.millstein.tsinglog.commons.constant.SystemConstant;
import com.millstein.tsinglog.commons.enums.ResultCode;
import com.millstein.tsinglog.exception.TsinglogException;
import com.millstein.tsinglog.commons.service.BaseService;
import com.millstein.tsinglog.mapper.biz.RoleMapper;
import com.millstein.tsinglog.model.dto.role.PermissionAssignDTO;
import com.millstein.tsinglog.model.dto.role.RoleSaveDTO;
import com.millstein.tsinglog.model.pojo.Role;
import com.millstein.tsinglog.model.vo.result.PageResult;
import com.millstein.tsinglog.service.RoleService;
import com.millstein.tsinglog.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.List;
import java.util.Map;

@Service
public class RoleServiceImpl extends BaseService implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserService userService;

    @Override
    public List<Role> getAllRoles() {
        Example example = new Example(Role.class);
        Example.Criteria criteria = example.createCriteria();

        criteria.andNotEqualTo("roleName", SystemConstant.ROOT_NAME);
        criteria.andEqualTo("status", SystemConstant.STATUS_ENTITY_NORMAL);
        criteria.andEqualTo("usable", SystemConstant.USABLE_ENTITY_ON);

        List<Role> list = roleMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }
        return list;
    }

    @Override
    public PageResult getRoleByPage(Integer currentPage, Integer pageSize, String keyword) {

        if (currentPage == null) {
            currentPage = SystemConstant.DEFAULT_CURRENT_PAGE;
        }
        if (pageSize == null) {
            pageSize = SystemConstant.DEFAULT_PAGE_SIZE;
        }

        Example example = new Example(Role.class);
        Example.Criteria criteria = example.createCriteria();

        if (StringUtils.isNotBlank(keyword)) {
            criteria.andLike("roleName", "%" + keyword + "%");
        }

        criteria.andEqualTo("status", SystemConstant.STATUS_ENTITY_NORMAL);

        example.setOrderByClause("update_time desc");

        PageHelper.startPage(currentPage, pageSize);
        List<Role> roles = roleMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(roles)) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }

        PageInfo<Role> pageInfo = new PageInfo<>(roles);

        return new PageResult(pageInfo.getTotal(), pageInfo.getPages(), roles);
    }

    @Override
    public void changeUsable(Long id, Short usable) {

        if (id == null || usable == null) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }

        Integer count = userService.getUserCountByRole(id);
        if (count != 0) {
            throw new TsinglogException(ResultCode.EXIST_USER_BELONG_ROLE);
        }

        Role criteria = new Role();
        criteria.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        criteria.setId(id);
        Role dbRole = roleMapper.selectOne(criteria);
        if (dbRole == null) {
            throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
        }

        dbRole.setUpdateTime(getCurrentDateStr());
        dbRole.setUsable(usable);

        int result = roleMapper.updateByPrimaryKey(dbRole);
        if (result != 1) {
            throw new TsinglogException(ResultCode.UPDATE_FAILURE);
        }
    }

    @Override
    @Transactional
    public void deleteByIds(List<Long> ids) {

        if (CollectionUtils.isEmpty(ids)) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }

        for (Long id : ids) {
            Integer count = userService.getUserCountByRole(id);
            if (count != 0) {
                throw new TsinglogException(ResultCode.EXIST_USER_BELONG_ROLE);
            }

            Role dbRole = roleMapper.selectRoleByPrimaryKey(id);
            if (dbRole == null) {
                throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
            }

            dbRole.setUpdateTime(getCurrentDateStr());
            dbRole.setStatus(SystemConstant.STATUS_ENTITY_DELETE);

            int result = roleMapper.updateByPrimaryKey(dbRole);
            if (result != 1) {
                throw new TsinglogException(ResultCode.UPDATE_FAILURE);
            }
        }

    }

    private Role getRoleByRoleName(String roleName) {
        Role role = new Role();
        role.setRoleName(roleName);
        role.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        return roleMapper.select(role).size() == 0 ? null: roleMapper.select(role).get(0);
    }

    @Override
    public void insertRole(RoleSaveDTO roleSaveDTO) {

        // 有重名的角色名称就报错
        if (this.getRoleByRoleName(roleSaveDTO.getRoleName()) != null) {
            throw new TsinglogException(ResultCode.EXIST_ROLE_NAME);
        }

        Role role = new Role();

        role.setRoleName(roleSaveDTO.getRoleName());
        role.setDescription(roleSaveDTO.getDescription());
        role.setSort(roleSaveDTO.getSort());
        role.setUsable(SystemConstant.USABLE_ENTITY_ON);
        role.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        role.setCreateTime(getCurrentDateStr());
        role.setUpdateTime(getCurrentDateStr());

        int result = roleMapper.insert(role);
        if (result != 1) {
            throw new TsinglogException(ResultCode.INSERT_FAILURE);
        }
    }

    @Override
    public void updateRole(RoleSaveDTO roleSaveDTO) {

        // 有重名的角色名称就报错
        if (this.getRoleByRoleName(roleSaveDTO.getRoleName()) != null) {
            throw new TsinglogException(ResultCode.EXIST_ROLE_NAME);
        }

        Long id = roleSaveDTO.getId();

        if (id == null) {
            throw new TsinglogException(ResultCode.PARAM_NOT_COMPLETE);
        }

        // 获取状态为正常的此id对应的角色信息
        Role dbRole = roleMapper.selectRoleByPrimaryKey(id);
        if (dbRole == null) {
            throw new TsinglogException(ResultCode.HANDLE_DATA_NOT_EXISTED);
        }

        dbRole.setRoleName(roleSaveDTO.getRoleName());
        dbRole.setDescription(roleSaveDTO.getDescription());
        dbRole.setSort(roleSaveDTO.getSort());
        dbRole.setUpdateTime(getCurrentDateStr());

        int result = roleMapper.updateByPrimaryKey(dbRole);
        if (result != 1) {
            throw new TsinglogException(ResultCode.UPDATE_FAILURE);
        }
    }

    @Override
    @Transactional
    public void assignPermission(PermissionAssignDTO permissionAssignDTO) {

        if (CollectionUtils.isEmpty(permissionAssignDTO.getPermissionIds())) {
            throw new TsinglogException(ResultCode.PARAM_NOT_COMPLETE);
        }

        // 1.删除原有的记录
        List<Map<String, Object>> relations = roleMapper.getMultipleRelations(permissionAssignDTO.getRoleId());
        if (!CollectionUtils.isEmpty(relations)) {
            int result = roleMapper.deleteMultipleRelations(permissionAssignDTO.getRoleId());
            if (result != relations.size()) {
                throw new TsinglogException(ResultCode.ASSIGN_PERMISSION_FAILURE);
            }
        }

        // 2.新增现在的记录
        List<Long> ids = permissionAssignDTO.getPermissionIds();
        for (Long pid: ids) {
            int result = roleMapper.insertMultipleRelations(permissionAssignDTO.getRoleId(), pid, getCurrentDateStr());
            if (result != 1) {
                throw new TsinglogException(ResultCode.ASSIGN_PERMISSION_FAILURE);
            }
        }
    }

}
